/*
 * $$Id: MessageProcessor.java,v 1.14 2004/05/30 20:03:56 bel70 Exp $$
 *
 * ***** BEGIN LICENSE BLOCK *****
 * The contents of this file are subject to the Mozilla Public License
 * Version 1.1 (the "License"); you may not use this file except in
 * compliance with the License. You may obtain a copy of the License
 * at http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS"
 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
 * the License for the specific language governing rights and
 * limitations under the License.
 *
 * The Original Code is jforum forum code.
 *
 * The Initial Developer of the Original Code is the JResearch, Org.
 * Portions created by the Initial Developer are Copyright (C) 2004
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *              Dmitry Belov <bel@jresearch.org>
 *
 * ***** END LICENSE BLOCK ***** */
package com.jred.jforum.util;

import org.apache.oro.text.PatternCacheLRU;
import org.apache.oro.text.perl.Perl5Util;

import org.apache.struts.util.MessageResources;


import org.tiling.memo.LruCacheFactory;

import java.text.MessageFormat;

import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.ResourceBundle;

/**
 * DOCUMENT ME!
 * 
 * @author dbelov
 */
public class MessageProcessor {

    private static MessageProcessor ourInstance;

    private static PatternCacheLRU cache = new PatternCacheLRU(50);

    private static Map resultCache = new LruCacheFactory(1000).createCache();

    private static HashMap emoticonsMap;

    private static final String EMOTICON_IMG_TAG = "<img src=\"{0}images/emoticons/{1}.gif\" alt=\"{2}\" title=\"{2}\">";

    private Perl5Util perlUtil;

    /**
     * DOCUMENT ME!
     * 
     * @param bundle
     *            DOCUMENT ME!
     */
    public synchronized static void setEmoticonsMap(ResourceBundle bundle) {
        Enumeration keys = bundle.getKeys();
        emoticonsMap = new HashMap();

        while (keys.hasMoreElements()) {
            String key = (String) keys.nextElement();
            String pattern = bundle.getString(key);

            emoticonsMap.put(key, HtmlCodec.encode(pattern));
        }
    }

    /**
     * DOCUMENT ME!
     * 
     * @return DOCUMENT ME!
     */
    public static HashMap getEmoticonsMap() {
        return emoticonsMap;
    }

    /**
     * Method <code>getInstance</code> return instance
     * 
     * @return instance
     */
    public synchronized static MessageProcessor getInstance() {
        if (ourInstance == null) {
            ourInstance = new MessageProcessor();
        }

        return ourInstance;
    }

    private MessageProcessor() {
        perlUtil = new Perl5Util(cache);
    }

    /**
     * DOCUMENT ME!
     * 
     * @param result
     *            DOCUMENT ME!
     * @param cutToLength
     *            DOCUMENT ME!
     * @param messages
     *            DOCUMENT ME!
     * 
     * @return DOCUMENT ME!
     */
    public String prepareMessage(String result, int cutToLength,
            MessageResources messages) {
        String key = Integer.toString(result.hashCode()) + cutToLength;
        Object value = resultCache.get(key);

        if ((value == null) && !resultCache.containsKey(key)) {
            value = prepare(result, cutToLength, messages);
            resultCache.put(key, value);
        }

        return (String) value;
    }

    private String prepare(String result, int cutToLength,
            MessageResources messages) {

        if (cutToLength > 0) {
            result = perlUtil.substitute("s/\\[(.*?)\\]/\r/gsi", result);

            if (result.length() > cutToLength) {
                result = result.substring(0, cutToLength);
                result += "...";
            }
        } else {
            // String expression="s/pattern/replacement/gsi"
            result = perlUtil.substitute(
                    "s/\\[b\\](.*?)\\[\\/b\\]/<strong>$1<\\/strong>/gsi",
                    result);
            result = perlUtil.substitute(
                    "s/\\[i\\](.*?)\\[\\/i\\]/<em>$1<\\/em>/gsi", result);
            result = perlUtil
                    .substitute(
                            "s/\\[url\\](http[s]?:\\/\\/)?(.*?)\\[\\/url\\]/<A HREF=\"$1$2\" TARGET=\"_blank\">$2<\\/A>/gsi",
                            result);
            result = perlUtil
                    .substitute(
                            "s/\\[url=(http[s]?:\\/\\/)?(.*?)\\](.*?)\\[\\/url\\]/<A HREF=\"$1$2\" TARGET=\"_blank\">$3<\\/A>/gsi",
                            result);
            result = perlUtil
                    .substitute(
                            "s/\\[email\\](.*?)\\[\\/email\\]/<A HREF=\"mailto:$1\">$1<\\/A>/gsi",
                            result);
            result = perlUtil
                    .substitute(
                            "s/\\[img\\](http:\\/\\/)?(.*?)\\[\\/img\\]/<IMG SRC=\"http:\\/\\/$2\" BORDER=0>/gsi",
                            result);
            result = perlUtil.substitute(
                    "s/\\[HR\\]/<hr size=\"1\" width=\"90%\" noshade>/gsi",
                    result);
            result = perlUtil.substitute("s/\\[QUOTE\\]/<blockquote>/gsi",
                    result);
            result = perlUtil.substitute(
                    "s/\\[\\/QUOTE\\]/<\\/blockquote>/gsi", result);
            result = perlUtil.substitute(
                    "s/\\[code\\](.*?)\\[\\/code\\]/<code>$1<\\/code>/gsi",
                    result);
            result = perlUtil.substitute("s/\\n/<br>/g", result);
        }

        return result;
    }

    /**
     * DOCUMENT ME!
     * 
     * @param result
     *            DOCUMENT ME!
     * 
     * @return DOCUMENT ME!
     */
    public String nl2br(String result) {
        return perlUtil.substitute("s/\\n/<br>/g", result);
    }

    /**
     * DOCUMENT ME!
     * 
     * @param result
     *            DOCUMENT ME!
     * @param messages
     *            DOCUMENT ME!
     * 
     * @return DOCUMENT ME!
     * 
     * @throws ConfiguratorException
     *             DOCUMENT ME!
     */

    //TODO - samples in TipsAndTrics page
    public String processEmoticons(String result, MessageResources messages) {
        Iterator it = emoticonsMap.keySet().iterator();
        Object[] args = {
                "/jforum/", "", "" };

        while (it.hasNext()) {
            String key = (String) it.next();
            String pattern = (String) emoticonsMap.get(key);

            args[1] = key;
            args[2] = messages.getMessage(key);

            result = replace(result, pattern, MessageFormat.format(
                    EMOTICON_IMG_TAG, args));
        }

        return result;
    }

    /**
     * DOCUMENT ME!
     * 
     * @param result
     *            DOCUMENT ME!
     * @param pattern
     *            DOCUMENT ME!
     * @param replace
     *            DOCUMENT ME!
     * 
     * @return DOCUMENT ME!
     * 
     * @throws IllegalArgumentException
     *             DOCUMENT ME!
     */
    public String replace(String result, String pattern, String replace) {
        if (result == null) { throw new IllegalArgumentException(
                "result parameter, value = " + result); }

        if (replace == null) { throw new IllegalArgumentException(
                "replace parameter, value = " + replace); }

        if ((pattern == null) || "".equals(pattern)) { throw new IllegalArgumentException(
                "pattern parameter, value = " + pattern); }

        if ("".equals(result)) { return result; }

        int s = 0;
        int e = 0;
        StringBuffer sb = new StringBuffer(result);

        while ((e = sb.indexOf(pattern, s)) > -1) {
            sb.replace(e, e + pattern.length(), replace);
            s = e + replace.length();
        }

        return sb.toString();
    }
}